home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 4 / ETO Development Tools 4.iso / Tools - Objects / MacApp / MacApp 3.0a2 / Libraries / UTearOffMenuView.cp < prev    next >
Encoding:
Text File  |  1991-05-01  |  12.1 KB  |  421 lines  |  [TEXT/MPS ]

  1. /*
  2.   • List units defining any constants, types or classes that are required for your implementation
  3.   section (e.g. Packages or Errors)
  4.   • Also list units defining the classes that you declared EXTERNAL in the interface section
  5.   or wish to use in the implementation section.
  6.   • Also list the units required by the interfaces of the above units.
  7. */
  8. #include "UTearOffMenuView.h"
  9.  
  10. #ifndef __UGEOMETRY__
  11. #include <UGeometry.h>
  12. #endif
  13.  
  14. #ifndef __UWindow__
  15. #include "UWindow.h";
  16. #endif
  17.  
  18. #ifndef __UFailure__
  19. #include "UFailure.h";
  20. #endif
  21.  
  22. #ifndef __TEXTEDIT__
  23. #include "TextEdit.h";
  24. #endif
  25.  
  26. #ifndef __UMacAppUtilities__
  27. #include "UMacAppUtilities.h";
  28. #endif
  29.  
  30. #ifndef __UPatch__
  31. #include "UPatch.h";
  32. #endif
  33.  
  34. #ifndef __DIALOGS__
  35. #include "Dialogs.h";
  36. #endif
  37.  
  38. #ifndef __UMacAppGlobals__
  39. #include "UMacAppGlobals.h";
  40. #endif
  41.  
  42. #ifndef __ERRORS__
  43. #include "Errors.h";
  44. #endif
  45.  
  46. #ifndef __TOOLUTILS__
  47. #include "ToolUtils.h";
  48. #endif
  49.  
  50. //--------------------------------------------------------------------------------------------------
  51. #pragma segment TearOffDoCommand
  52.  
  53. pascal void TShowTearOffWindowCmd::Initialize(void)// override 
  54.  
  55. {
  56.     inherited::Initialize();
  57.     fTearOffWindow = NULL;
  58.     fWhere = gZeroPt;
  59. }
  60.  
  61. //--------------------------------------------------------------------------------------------------
  62. #pragma segment TearOffDoCommand
  63.  
  64. pascal void TShowTearOffWindowCmd::IShowTearOffWindowCmd(TWindow* tearOffWindow,
  65.                                                          Point where)
  66.  
  67. {
  68.     this->INoChangesCommand(0, NULL, NULL);
  69.     fTearOffWindow = tearOffWindow;
  70.     fWhere = where;
  71. }
  72.  
  73. //--------------------------------------------------------------------------------------------------
  74. #pragma segment TearOffDoCommand
  75.  
  76. pascal void TShowTearOffWindowCmd::DoIt(void)    // override 
  77.  
  78. {
  79.     if (fTearOffWindow)
  80.     {
  81.         fTearOffWindow->Locate(fWhere, kDontInvalidate);// move it to its new home 
  82.         fTearOffWindow->fMustForceOnScreen = TRUE;// so the Open will call ForceOnScreen 
  83.         fTearOffWindow->fForcedOnScreen = FALSE;
  84.         fTearOffWindow->Open();                    // show the torn-off window 
  85.         fTearOffWindow->Select();                // select the torn-off window 
  86.     }
  87. }
  88.  
  89. //--------------------------------------------------------------------------------------------------
  90. #pragma segment TearOffFields
  91.  
  92. pascal void TShowTearOffWindowCmd::Fields(TObject* obj)// override 
  93.  
  94. {
  95.     obj->DoToField("TShowTearOffWindowCmd", (Ptr)NULL, bClass);
  96.     inherited::Fields(obj);
  97. }
  98.  
  99. //--------------------------------------------------------------------------------------------------
  100. #pragma segment TearOffInit
  101.  
  102. pascal void TTearOffTracker::Initialize(void)    // override 
  103.  
  104. {
  105.     inherited::Initialize();
  106.     fExitTracking = FALSE;
  107.     fOrigin = gZeroPt;
  108.     fTearOffMenu = NULL;
  109.     fTearOffWindowOutline = NULL;
  110. }
  111.  
  112. //--------------------------------------------------------------------------------------------------
  113. #pragma segment TearOffInit
  114.  
  115. pascal void TTearOffTracker::ITearOffTracker(Point hitPt,
  116.                                              TTearOffMenuView* tearOffMenu)
  117.  
  118. {
  119.     VPoint theMouse;
  120.  
  121.     theMouse.v = hitPt.v;
  122.     theMouse.h = hitPt.h;
  123.     this->ITracker(0, NULL, NULL, NULL, theMouse);
  124.  
  125.     fCanUndo = FALSE;
  126.     fCausesChange = FALSE;
  127.     fFreeOnCompletion = FALSE;
  128.  
  129.     fTearOffMenu = tearOffMenu;
  130.  
  131.     fTearOffWindowOutline = MakeNewRgn();        // !!! needs failure handler
  132. }
  133.  
  134. //--------------------------------------------------------------------------------------------------
  135. #pragma segment TearOffClose
  136.  
  137. pascal void TTearOffTracker::Free(void)            // override 
  138.  
  139. {
  140.     fTearOffWindowOutline = DisposeIfRgnHandle(fTearOffWindowOutline);
  141.  
  142.     inherited::Free();
  143. }
  144.  
  145. //--------------------------------------------------------------------------------------------------
  146. #pragma segment TearOffDoCommand
  147.  
  148. pascal void TTearOffTracker::DoIt(void)
  149.  
  150. {
  151.     Point where;
  152.     TWindow * aTearOffWindow;
  153.     TShowTearOffWindowCmd * aShowTearOffWindowCmd;
  154.  
  155.  
  156.     if (!fExitTracking)                            /* ensure that we didn't exit the tracking
  157.                                                   loop */
  158.     {
  159.         aTearOffWindow = fTearOffMenu->fTearOffWindow;
  160.  
  161.         where.v = (*fTearOffWindowOutline)->rgnBBox.top + aTearOffWindow->fContRgnInset.v;
  162.         where.h = (*fTearOffWindowOutline)->rgnBBox.left + aTearOffWindow->fContRgnInset.h;
  163.  
  164.         if (aTearOffWindow != NULL)
  165.         {
  166.             /* NOTE: we can't just move and show the tear off window here because the menu that
  167.               we want to tearx off is currently displayed on the screen and the menu manager has
  168.               cached the bits underneath the currently displayed menu and we might be moving our
  169.               floating window into that territory thus invalidating the menu manager's cache (which
  170.               the menu manager will blit back in place momentarily). To work-around this "feature"
  171.               we'll simply post a command which will do the work later. Isn't MacApp wonderful! */
  172.             aShowTearOffWindowCmd = new TShowTearOffWindowCmd;
  173.             aShowTearOffWindowCmd->IShowTearOffWindowCmd(aTearOffWindow, where);
  174.             fTearOffMenu->PostCommand(aShowTearOffWindowCmd);
  175.         }
  176.  
  177.     }
  178. }
  179.  
  180. //--------------------------------------------------------------------------------------------------
  181. #pragma segment TearOffDoCommand
  182.  
  183. pascal void TTearOffTracker::TrackFeedback(TrackPhase /* aTrackPhase */,
  184.                                         const VPoint& /* anchorPoint */,
  185.                                         const VPoint& /* previousPoint */,
  186.                                         const VPoint& /* nextPoint */,
  187.                                         Boolean mouseDidMove,
  188.                                         Boolean /* turnItOn */)
  189. {
  190.     if (mouseDidMove && !EmptyRgn(fTearOffWindowOutline))
  191.     {
  192.         PenPat(qd.gray);
  193.         FrameRgn(fTearOffWindowOutline);        // draw/erase 
  194.     }
  195. }
  196.  
  197. //--------------------------------------------------------------------------------------------------
  198. #pragma segment TearOffDoCommand
  199.  
  200. pascal TTracker* TTearOffTracker::TrackMouse(TrackPhase aTrackPhase,
  201.                                              VPoint& ,
  202.                                              VPoint& previousPoint,
  203.                                              VPoint& nextPoint,
  204.                                              Boolean)
  205.  
  206. {
  207.     TWindow * aTearOffWindow;
  208.     short verticalOffset;
  209.     short horizontalOffset;
  210.     Boolean rgnsWereBuilt;
  211.  
  212.     fExitTracking =!PtInRgn(Point(nextPoint), fTearOffMenu->fTearOffTrackingRgn);
  213.  
  214.     if (aTrackPhase == trackBegin)
  215.     {
  216.         aTearOffWindow = fTearOffMenu->fTearOffWindow;
  217.         if (aTearOffWindow != NULL)
  218.         {
  219.             rgnsWereBuilt = aTearOffWindow->BuildWindowRgns(kBuild);
  220.             CopyRgn(((WindowPeek)aTearOffWindow->fWMgrWindow)->strucRgn, fTearOffWindowOutline);
  221.             aTearOffWindow->BuildWindowRgns(rgnsWereBuilt);
  222.  
  223.             // move the outline to the topleft of the window mgr graf port 
  224.             OffsetRgn(fTearOffWindowOutline, -(*fTearOffWindowOutline)->rgnBBox.left, -(*fTearOffWindowOutline)->rgnBBox.top);
  225.  
  226.             // move the outline so that it's centered at the mouse 
  227.             verticalOffset = ((*fTearOffWindowOutline)->rgnBBox.Length(vSel)) / 2;
  228.             horizontalOffset = ((*fTearOffWindowOutline)->rgnBBox.Length(hSel)) / 2;
  229.             OffsetRgn(fTearOffWindowOutline, (short)(previousPoint.h - horizontalOffset), (short)(previousPoint.v - verticalOffset));
  230.         }
  231.         //aTearOffWindow != NULL
  232.     }
  233.     else
  234.         OffsetRgn(fTearOffWindowOutline, (short)(nextPoint.h - previousPoint.h), (short)(nextPoint.v - previousPoint.v));
  235.     return this;
  236. }
  237.  
  238. //--------------------------------------------------------------------------------------------------
  239. #pragma segment TearOffDoCommand
  240.  
  241. pascal Boolean TTearOffTracker::IsDoneTracking(void)// override 
  242.  
  243. {
  244.     return ((!StillDown()) || fExitTracking);
  245. }
  246.  
  247. //--------------------------------------------------------------------------------------------------
  248. #pragma segment MTearOffFields
  249.  
  250. pascal void TTearOffTracker::Fields(TObject* obj)// override 
  251.  
  252. {
  253.     obj->DoToField("TTearOffTracker", (Ptr)NULL, bClass);
  254.     inherited::Fields(obj);
  255. }
  256.  
  257. //--------------------------------------------------------------------------------------------------
  258. #pragma segment TearOffInit
  259.  
  260. pascal void TTearOffMenuView::Initialize(void)    // override 
  261.  
  262. {
  263.     inherited::Initialize();
  264.     fTearOffTracker = NULL;
  265.     fTearOffTrackingRgn = NULL;
  266.     fTearOffWindow = NULL;
  267. }
  268.  
  269. //--------------------------------------------------------------------------------------------------
  270. #pragma segment TearOffInit
  271.  
  272. pascal void TTearOffMenuView::ITearOffMenuView(short rsrcID,
  273.                                                short menuWidth,
  274.                                                short menuHeight,
  275.                                                TWindow* tearOffWindow)
  276.  
  277. {
  278.     this->IMenuView(rsrcID, menuWidth, menuHeight);
  279.     fTearOffTrackingRgn = MakeNewRgn();
  280.     fTearOffWindow = tearOffWindow;
  281.  
  282.     this->InstallTearOffTracker();
  283. }
  284.  
  285. //--------------------------------------------------------------------------------------------------
  286. #pragma segment TearOffInit
  287.  
  288. pascal void TTearOffMenuView::InstallTearOffTracker(void)
  289. /* For the sake of efficiency when tracking a tear-off, we'll create the tear-off tracker and
  290.   keep it with us, so we don't need to allocate a new tracker every time we tear off a menu. If you
  291.   want a different tracker in your subclass of TTearOffMenuView, then override this method. */
  292.  
  293. {
  294.     TTearOffTracker * tearOffTracker;
  295.  
  296.     tearOffTracker = new TTearOffTracker;
  297.     tearOffTracker->ITearOffTracker(gZeroPt, this);
  298.     fTearOffTracker = tearOffTracker;
  299. }
  300.  
  301. //--------------------------------------------------------------------------------------------------
  302. #pragma segment TearOffClose
  303.  
  304. pascal void TTearOffMenuView::Free(void)        // override 
  305.  
  306. {
  307.     fTearOffTracker = (TTearOffTracker *)FreeIfObject(fTearOffTracker);
  308.     fTearOffTrackingRgn = DisposeIfRgnHandle(fTearOffTrackingRgn);
  309.  
  310.     inherited::Free();
  311. }
  312.  
  313. //--------------------------------------------------------------------------------------------------
  314. #pragma segment TearOffRes
  315.  
  316. pascal void TTearOffMenuView::HandleChooseMessage(short,
  317.                                                   MenuHandle,
  318.                                                   Rect& menuRect,
  319.                                                   Point hitPt,
  320.                                                   short& whichItem)// override 
  321.  
  322. {
  323.     short newItem;
  324.     Rect hitRect;
  325.     TToolboxEvent * event = NULL;
  326.     EventRecord anEventRecord;
  327.     Boolean saveTrackingInMenu;
  328.  
  329.  
  330.     // so that trackers know that they're tracking in menus 
  331.     saveTrackingInMenu = gTrackingInMenu;
  332.     gTrackingInMenu = TRUE;
  333.  
  334.     newItem = kNoMenuItem;                        // default return 
  335.  
  336.     if (this->IsEnabled())                            // menu enabled 
  337.     {
  338.         // see if point is within hit area 
  339.         this->GetQDExtent(hitRect);
  340.         hitRect += fBorder;
  341.         if (hitRect.Contains(hitPt))            // in menu view (not border) 
  342.         {
  343.             // NOTE: Either your subclass of TTearOffMenuView should override DoMouseCommand or one of
  344.             // TTearOffMenuView's view's subview's should override DoMouseCommand so that
  345.             // it creates and posts a TTracker. TTearOffMenuView's override of PostCommand
  346.             // will ensure that the tracker is tracked immediately. The tracker, having
  347.             // been posted and tracked, will then get executed next time PerformCommand is
  348.             // called. So, when we're done with HandleMouseDown below, we simply tell the
  349.             // menu manager that no menu item was selected, ie newItem == kNoMenuItem.
  350.  
  351.             event = new TToolboxEvent;
  352.             event->IToolboxEvent(NULL);
  353.             this->CreateMouseDownEventInfo(hitPt, anEventRecord, event);
  354.             this->HandleMouseDown(hitPt, event, gStdHysteresis);
  355.             event = (TToolboxEvent *)FreeIfObject(event);
  356.         }
  357.         else
  358.         {                                        /* determine if we should track a tear off
  359.                                                   image */
  360.             LocalToGlobal(hitPt);
  361.             if (PtInRgn(hitPt, this->GetTearOffTrackingRgn(menuRect)))
  362.             {
  363.                 fTearOffTracker->fInitialPt = hitPt;
  364.                 this->PostCommand(fTearOffTracker);
  365.             }
  366.         }
  367.     }
  368.     else
  369.         this->UpdateHighlight(whichItem, newItem);    // Update highlighting 
  370.  
  371.     gTrackingInMenu = saveTrackingInMenu;
  372.  
  373.     // Tell MenuManager about new item 
  374.     whichItem = newItem;
  375. }
  376.  
  377. //--------------------------------------------------------------------------------------------------
  378. #pragma segment TearOffRes
  379.  
  380. pascal RgnHandle TTearOffMenuView::GetTearOffTrackingRgn(const Rect& menuRect)
  381. // This function returns fTearOffTrackingRgn 
  382.  
  383. {
  384.     Rect rgnRect;
  385.  
  386.     if (EmptyRgn(fTearOffTrackingRgn))
  387.     {
  388.         Rect rect = menuRect;
  389.         
  390.         // calculate the tracking region for the tearoff image
  391.         LocalToGlobal(rect[topLeft]);
  392.         LocalToGlobal(rect[botRight]);
  393.         SetRect(rgnRect, rect.left - kTearOffMargin, rect.top, rect.right + kTearOffMargin, rect.bottom + kTearOffMargin);
  394.  
  395. #if qDebug
  396.         UseTempRgn("TTearOffMenuView.HandleDefproc");
  397. #endif
  398.  
  399.         RectRgn(gTempRgn, rgnRect);
  400.         DiffRgn(GetGrayRgn(), gTempRgn, fTearOffTrackingRgn);
  401. #if qDebug
  402.         DoneWithTempRgn();
  403. #endif
  404.  
  405.         InsetRgn(fTearOffTrackingRgn, 4, 4);
  406.     }
  407.     return fTearOffTrackingRgn;
  408. }
  409.  
  410. //--------------------------------------------------------------------------------------------------
  411. #pragma segment TearOffFields
  412.  
  413. pascal void TTearOffMenuView::Fields(TObject* obj)// override 
  414.  
  415. {
  416.     obj->DoToField("TTearOffMenuView", (Ptr)NULL, bClass);
  417.     inherited::Fields(obj);
  418. }
  419.  
  420.  
  421.